home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / GDTimeClut.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-15  |  5.0 KB  |  119 lines  |  [TEXT/KAHL]

  1. /*
  2. GDTimeClut.c
  3.  
  4. error=GDTimeClut(device,GDSetEntries,clutEntries,&s,&frames,&missingFrames,&frameRate);
  5.  
  6. GDTimeClut measures how long it takes to load the clut. It measures in two kinds
  7. of units simultaneously, frames and seconds. You supply the function to be
  8. tested, e.g. SetEntriesQuickly or GDSetEntries. (If mode>eightBitMode GDTimeClut
  9. will automatically substitute GDDirectSetEntries for GDSetEntries.) The second
  10. argument, "clutEntries", specifies how many clut entries you want to update each
  11. time, or zero for all, e.g. all 256 in 8-bit mode. It also measures the frame
  12. rate independently, which it returns, after using it to estimate how many frame
  13. interrupts were missed during each clut load. If there's at least one frame
  14. missing or if the frame count is very small, less than 0.5 per call, then it
  15. estimates the frames directly from the time. You may substitute NULL for any of
  16. the pointer-to-double arguments.
  17.  
  18. Use GDTimeClut() instead of the old functions, GDFramesPerClutUpdate,
  19. GDClutUpdateRate, and GDTimeClutUpdate in GDFrameRate.c. They are now obsolete.
  20.  
  21. It is of interest to time GDSetEntries (and its sibling GDDirectSetEntries) at
  22. both normal (zero) and high (7) processor interrupt priority, because some
  23. drivers are asynchronous when run at low priority, returning immediately and
  24. deferring the actual clut loading until the vbl interrupt occurs, but Apple
  25. specifies that all drivers must be synchronous when run at high priority. You do
  26. this by supplying the new routine GDSetEntriesByTypeHighPriority().
  27.  
  28. Similarly, while the problem of multiple interrupts per frame is dealt with
  29. satisfactorily by VBLInstall.c, using the scheme suggested by Raynald Comtois,
  30. it is of technical interest to follow up the report that there are no extra
  31. interrupts if the processor instruction cache is disabled. One theory to account
  32. for this is that perhaps disabling the cache causes the interrupt service
  33. routine to take long enough that the hardware interrupt pulse has terminated
  34. before the routine exits. Thus I would like to write a routine called
  35. GDSetEntriesNoCache, but I don't know how to disable the cache.
  36.  
  37. HISTORY:
  38. 3/11/93    dgp created it, based on GDTimeClutUpdate and GDFramesPerClutUpdate in
  39. GDFrameRate.c. The enhancements are 1. you supply the function to be tested,
  40. either SetEntriesQuickly or GDSetEntries. 2. It doesn't print or exit, always
  41. returning with an informative OSErr. 3. It measures frame rate independently,
  42. which it returns, and also uses it to estimate how many frame interrupts were
  43. missed during each clut load. 4. If there's at least one frame missing or if the
  44. frame count is very small, less than 0.5 per call, then it estimates the frames
  45. directly from the time.
  46.  
  47. */
  48. #include <VideoToolbox.h>
  49. #include <math.h>
  50. #define CALLS 30
  51. // Original typedef is in VideoToolbox.h
  52. //typedef OSErr (*SetEntriesFunction)(GDHandle device,short start,short count
  53. //    ,ColorSpec *aTable);
  54.  
  55. OSErr GDTimeClut(GDHandle device,SetEntriesFunction function,short clutEntries
  56.     ,double *sPtr,double *framesPtr,double *missingFramesPtr,double *frameRatePtr)
  57. {
  58.     OSErr error;
  59.     short mode,clutSize,i;
  60.     ColorSpec *table,*linearTable=NULL;
  61.     static VBLTaskAndA5 vblData;
  62.     long frames;
  63.     Timer *timer;
  64.     double s,missingFrames,frameRate;
  65.  
  66.     if(sPtr!=NULL)*sPtr=NAN;
  67.     if(framesPtr!=NULL)*framesPtr=NAN;
  68.     if(missingFramesPtr!=NULL)*missingFramesPtr=NAN;
  69.     if(frameRatePtr!=NULL)*frameRatePtr=NAN;
  70.     clutSize=GDClutSize(device);
  71.     if(clutEntries<0 || clutEntries>clutSize)return 1;
  72.     if(clutEntries==0)clutEntries=clutSize;
  73.     error=GDGetMode(device,&mode,NULL,NULL);
  74.     if(error)mode=(**device).gdMode;
  75.     if(mode>eightBitMode){
  76.         if(function==GDSetEntries)function=GDDirectSetEntries;
  77.         table=linearTable=(ColorSpec *)NewPtr(clutSize*sizeof(linearTable[0]));
  78.         if(linearTable==NULL)return MemError();
  79.         for(i=0;i<clutSize;i++){
  80.             table->rgb.red=table->rgb.green=table->rgb.blue=(long)0xffff*i/(clutSize-1);
  81.             table++;
  82.         }
  83.     }else table=((**(**(**device).gdPMap).pmTable)).ctTable;
  84.     vblData.subroutine=NULL;                        // setup frame counter
  85.     error=VBLInstall(&vblData,device,CALLS*20);        // setup frame counter
  86.     if(error)return error;
  87.     timer=NewTimer();                                // setup timer
  88.     if(timer==NULL)return 1;                        // lacks Revised Time Manager.
  89.     vblData.vbl.vblCount=1;                            // Enable interrupt service routine
  90.     for(i=-1;i<CALLS;i++) {
  91.         error=(function)(device,0,clutEntries-1,table);
  92.         if(i==-1){
  93.             StartTimer(timer);
  94.             frames=vblData.framesLeft;
  95.         }
  96.         if(error)break;
  97.     }
  98.     frames-=vblData.framesLeft;
  99.     s=StopTimerSecs(timer);
  100.     VBLRemove(&vblData);
  101.     DisposeTimer(timer);
  102.     if(linearTable!=NULL)DisposePtr((Ptr)linearTable);
  103.     if(error)return error;
  104.     
  105.     // Estimate number of missing frames by discrepancy between frames and secs.
  106.     frameRate=GDFrameRate(device);
  107.     missingFrames=s*frameRate-frames;
  108.     
  109.     // Return results
  110.     if(sPtr!=NULL)*sPtr=s/CALLS;
  111.     if(framesPtr!=NULL){
  112.         if(fabs(missingFrames)>1. || frames<CALLS/2) *framesPtr=frameRate*s/CALLS;
  113.         else *framesPtr=frames/(double)CALLS;
  114.     }
  115.     if(missingFramesPtr!=NULL)*missingFramesPtr=missingFrames/CALLS;
  116.     if(frameRatePtr!=NULL)*frameRatePtr=frameRate;
  117.     return 0;
  118. }
  119.